﻿using System.Linq;
using Magiq.Providers.Sql.Query;
using Magiq.Tests.Sql.TestModel;
using Magiq.Tests.Support;
using NUnit.Framework;

namespace Magiq.Tests.Sql
{
    public class CompiledQueriesTest
    {
        [SetUp]
        public void SetUp()
        {
            MagiqToSqlTestConfigurator.Current.SetUp();
            domain = new CollectionTestDomain();
            MagiqToSqlTestConfigurator.Current.Persist(domain.ChildItems);
            MagiqToSqlTestConfigurator.Current.Persist(domain.Parents);
            domain.AddRelations();
            MagiqToSqlTestConfigurator.Current.Reload();
            parents = MagiqToSqlTestConfigurator.Current.GetQueryable<Parent>();
            childItems = MagiqToSqlTestConfigurator.Current.GetQueryable<ChildItem>();
        }

        [TearDown]
        public void TearDown()
        {
            MagiqToSqlTestConfigurator.Current.TearDown();
        }

        private CollectionTestDomain domain;
        private IQueryable<Parent> parents;
        private IQueryable<ChildItem> childItems;

        [Test]
        public void FromEntitySetCompiledWithNoArguments()
        {
            var compiled = parents.ToList().First().Query(x=>x.Items)
                .CompiledQuery("test", q => q.Where(x => x.Name == "lala").OrderBy(x => x.Id).Select(x => x.Id));

            var enumerableCollection = parents.ToList().First()
                .Items.Where(x => x.Name == "lala").OrderBy(x => x.Id).Select(x => x.Id);

            Assert.AreNotEqual(compiled.GetType(), enumerableCollection.GetType());

            var list1 = compiled.ToList();
            var lisTestClass2 = enumerableCollection.ToList();

            for (var i = 0; i < list1.Count; i++)
                list1[i].Should(Be.EqualTo(lisTestClass2[i]));
        }

        [Test]
        public void FromEntitySetCompiledWithOneArgument()
        {
            var compiled = parents.ToList().First()
                .Query(x => x.Items).CompiledQuery("test", (q, n) => q.Where(x => x.Name == n).OrderBy(x => x.Id).Select(x => x.Id), "lala");

            var enumerableCollection = parents.ToList().First()
                .Items.Where(x => x.Name == "lala").OrderBy(x => x.Id).Select(x => x.Id);

            Assert.AreNotEqual(compiled.GetType(), enumerableCollection.GetType());

            var list1 = compiled.ToList();
            var lisTestClass2 = enumerableCollection.ToList();

            for (var i = 0; i < list1.Count; i++)
                list1[i].Should(Be.EqualTo(lisTestClass2[i]));
        }


        [Test]
        public void FromTableCompiledWithTwoArguments()
        {
            var compiled = childItems.CompiledQuery("test", (q, n, m) => q.Where(x => x.Name.StartsWith(n) && x.Name.EndsWith(m)).OrderBy(x => x.Id).Select(x => x.Id), "l", "la");

            var enumerableCollection = childItems.Where(x => x.Name.StartsWith("l") && x.Name.EndsWith("la")).OrderBy(x => x.Id).Select(x => x.Id);

            Assert.AreNotEqual(compiled.GetType(), enumerableCollection.GetType());

            var list1 = compiled.ToList();
            var lisTestClass2 = enumerableCollection.ToList();

            for (var i = 0; i < list1.Count; i++)
                list1[i].Should(Be.EqualTo(lisTestClass2[i]));
        }

        [Test]
        public void FromTableCompiledWithNoArguments()
        {
            var compiled = childItems.CompiledQuery("test", q => q.Where(x => x.Name == "lala").OrderBy(x => x.Id).Select(x => x.Id));

            var enumerableCollection = childItems.Where(x => x.Name == "lala").OrderBy(x => x.Id).Select(x => x.Id);

            Assert.AreNotEqual(compiled.GetType(), enumerableCollection.GetType());

            var list1 = compiled.ToList();
            var lisTestClass2 = enumerableCollection.ToList();

            for (var i = 0; i < list1.Count; i++)
                list1[i].Should(Be.EqualTo(lisTestClass2[i]));
        }

        [Test]
        public void FromTableCompiledWithOneArgument()
        {
            var compiled = childItems.CompiledQuery("test", (q, n) => q.Where(x => x.Name == n).OrderBy(x => x.Id).Select(x => x.Id), "lala");

            var enumerableCollection = childItems.Where(x => x.Name == "lala").OrderBy(x => x.Id).Select(x => x.Id);

            Assert.AreNotEqual(compiled.GetType(), enumerableCollection.GetType());

            var list1 = compiled.ToList();
            var lisTestClass2 = enumerableCollection.ToList();

            for (var i = 0; i < list1.Count; i++)
                list1[i].Should(Be.EqualTo(lisTestClass2[i]));
        }


        [Test]
        public void FromEntitySetCompiledWithTwoArguments()
        {
            var compiled = parents.ToList().First()
                .Query(x => x.Items).CompiledQuery("test", (q, n, m) => q.Where(x => x.Name.StartsWith(n) && x.Name.EndsWith(m)).OrderBy(x => x.Id).Select(x => x.Id), "l", "la");

            var enumerableCollection = parents.ToList().First()
                .Items.Where(x => x.Name.StartsWith("l") && x.Name.EndsWith("la")).OrderBy(x => x.Id).Select(x => x.Id);

            Assert.AreNotEqual(compiled.GetType(), enumerableCollection.GetType());

            var list1 = compiled.ToList();
            var lisTestClass2 = enumerableCollection.ToList();

            for (var i = 0; i < list1.Count; i++)
                list1[i].Should(Be.EqualTo(lisTestClass2[i]));
        }
    }
}